//
// Created by hjie on 23-12-28.
//

#include "filter_graph_context.h"
#include "base_util.h"
#include <sstream>

FilterGraphContext::FilterGraphContext()
{
    m_filter_graph = nullptr;
}

FilterGraphContext::~FilterGraphContext()
{
    if (m_filter_graph)
    {
        avfilter_graph_free(&m_filter_graph);
        m_filter_graph = nullptr;
    }
}

bool FilterGraphContext::InitGraph()
{
    m_filter_graph = avfilter_graph_alloc();
    return true;
}

bool FilterGraphContext::AddFilterCtx(AVFilterContext *filter_ctx)
{
    m_filter_ctx_map[filter_ctx->name] = filter_ctx;
    return true;
}

AVFilterGraph *FilterGraphContext::GetFilterGraph()
{
    return m_filter_graph;
}

AVFilterContext *FilterGraphContext::GetFilterBufferCtx()
{
    return m_buffer_ctx;
}

AVFilterContext *FilterGraphContext::GetFilterBufferSinkCtx()
{
    return m_buffer_sink_ctx;
}

bool FilterGraphContext::InitBufferCtxForVideo(const VideoFilterParams & config)
{
    char args[1024];
    int length = 0;
    bzero(&args, sizeof(args));
    if (config.m_width > 0 && config.m_height > 0)
    {
        length += snprintf(args + length, sizeof(args) - length, "video_size=%dx%d:", config.m_width, config.m_height);
    }
    if (config.m_format >= 0)
    {
        length += snprintf(args + length, sizeof(args) - length, "pix_fmt=%d:", config.m_format);
    }
    if (config.m_timebase.den > 0 && config.m_timebase.num > 0)
    {
        length += snprintf(args + length, sizeof(args) - length, "time_base=%d/%d:", config.m_timebase.num, config.m_timebase.den);
    }
    if (config.m_framerate.den > 0 && config.m_framerate.num > 0)
    {
        length += snprintf(args + length, sizeof(args) - length, "frame_rate=%d/%d:", config.m_framerate.num, config.m_framerate.den);
    }
    args[length-1] = '\0';
    PrintLogMsg(args);

    const AVFilter * buffer_filter = avfilter_get_by_name("buffer");
    int result = avfilter_graph_create_filter(&m_buffer_ctx, buffer_filter, "in", args, nullptr, m_filter_graph);
    if (result < 0)
    {
        PrintLog(result);
        return false;
    }
    return true;
}

bool FilterGraphContext::InitBufferSinkForVideo()
{
    const AVFilter * filter = avfilter_get_by_name("buffersink");
    int result = avfilter_graph_create_filter(&m_buffer_sink_ctx, filter, "out", nullptr, nullptr, m_filter_graph);
    if (result < 0)
    {
        PrintLog(result);
        return false;
    }
    return true;
}

bool FilterGraphContext::ConfigGraph()
{
    int result = avfilter_graph_config(m_filter_graph, nullptr);
    if (result < 0)
    {
        PrintLog(result);
        return false;
    }
    else
    {
        char * ptr = avfilter_graph_dump(m_filter_graph, nullptr);
        if (ptr)
        {
            printf("%s.\n", ptr);
            av_free(ptr);
        }
        return true;
    }
}

